package br.edu.ufcg.msnlab2.grupo07.monteCarlo;

import java.util.List;
import java.util.Map;

import mathExpr.ExpressionConfiguration;
import br.edu.ufcg.msnlab2.MSNLabException;
import br.edu.ufcg.msnlab2.misc.Function;


/**
 * This class implements the simple strategy for solving an integration
 * using Monte Carlo method. Here a random set of n points is created and 
 * then these points are used to estimate the integral value.
 * @author David Candeia 
 * @author Felipe Leal
 */

public class PlainMonteCarloSolverImpl extends MonteCarloSolver implements PlainMonteCarloSolver{

	/**
	 * @throws MSNLabException 
	 * @see PlainMonteCarloSolver
	 */
	@Override
	public MonteCarloResult solve(Function function,
			Map<String, Tuple<Double, Double>> limits, long numberOfPoints)
			throws MSNLabException {
		//Sampling points
		Map<String, List<Double>> sampledPoints = samplePoints(limits, numberOfPoints);
//		System.out.println("Points "+sampledPoints.toString());
//		System.out.println("N Points "+numberOfPoints);
		
		//Calculating integration estimative
		double valuesSum = calculateFunctionValueInEachPoint(sampledPoints, function, numberOfPoints);
//		System.out.println("Values sum "+valuesSum);
		
		double volume = calculateVolume(limits);
//		System.out.println("Volume "+volume);
		
		double estimative = valuesSum * volume / numberOfPoints;
//		System.out.println("Integral Estimative "+estimative);
		
		//Calculating integration error
		double error = Math.sqrt(calculateVariance(function, sampledPoints, valuesSum / numberOfPoints, volume, numberOfPoints));
//		System.out.println("Error estimative "+error);
		
		MonteCarloResult result = new MonteCarloResult(error, estimative);
		
		return result;
	}
}
